/*
 * TestGenerator.cpp
 *
 *  Created on: 2012-04-22
 *      Author: mm
 */

#include "TestGenerator.h"
#include <iostream>
using namespace std;

TestGenerator* TestGenerator::instance_ = 0L;

void TestGenerator::addText(const Text& text)
{
	inputTexts_.push_back(text);
}

void TestGenerator::printTexts()
{
	for(Texts::size_type i = 0; i < inputTexts_.size(); i++)
	{
		for(Text::size_type j = 0; j < inputTexts_[i].size(); j++)
		std::cout << inputTexts_[i][j] << " | ";

		std::cout << std::endl;
	}
	std::cout << std::endl;
}

void TestGenerator::buildTextTable()
{
	Text temp;
	Text call = inputTexts_[inputTexts_.size()-1];
	bool bracketsOpen = false;


	textTable_.clear();

	for(unsigned int i = 0; i < call.size(); i++)
	{
		if(call[i].compare(0, 1, "@") == 0)
		{
			Text expanded = expandDefinition(call[i]);
			for(unsigned int j = 0; j < expanded.size(); j++)
				temp.push_back(expanded[j]);
			continue;
		}

		// aggregate possibilities from brackets into one Text
		if(bracketsOpen && call[i] != "]")
		{
			temp.push_back(call[i]);
			continue;
		}

		if(call[i] == "[")
		{
			bracketsOpen = true;
			continue;
		}

		if(call[i] == "]")
		{
			bracketsOpen = false;
			textTable_.push_back(temp);
			temp.clear();
		}

		else
		{
			temp.push_back(call[i]);
			textTable_.push_back(temp);
			temp.clear();
		}
	}


//	for(unsigned int i = 0; i < textTable_.size(); i++)
//	{
//		for(unsigned int j = 0; j < textTable_[i].size(); j++)
//			cout << textTable_[i][j] << " | ";
//
//		cout << endl;
//
//	}
}

TestGenerator::Text TestGenerator::expandDefinition(std::string s)
{
	Text result;
	std::string temp = s;
	temp.erase(0, 1); // delete "@"

	for(unsigned int i = 0; i < inputTexts_.size(); i++)
	{
		if(inputTexts_[i][0].find(temp) != std::string::npos) // matching definition found
		{
			for(unsigned int j = 2; j < inputTexts_[i].size(); j++) // omit name and initial space
			{
				if(inputTexts_[i][j] != "[" && inputTexts_[i][j] != "]")
				result.push_back(inputTexts_[i][j]);
			}
			return result;
		}
	}

	result.push_back(s);
	return result;
}

void TestGenerator::generate()
{
	status_ = 0;
	elementStatus_ = 0;

	buildTextTable();
	nextText(status_, 0);
}

void TestGenerator::nextText(int start, int element)
{
	// result found
	if((unsigned int) start >= textTable_.size() || (unsigned int)element > textTable_[start].size())
	{
			for(int i = 0; i < result_.size(); i++)
				cout << result_[i];
			cout << endl;
			return;
	}

	result_.push_back(textTable_[start][element]);

	nextText(++status_, 0);

	result_.pop_back();
	status_--;


	if((int)textTable_[status_].size() > 1 && (element + 1) != (int)textTable_[status_].size())
	{
		nextText(status_, ++element);
		element--;
	}

}


